// SetProperties.cpp

#include "StdAfx.h"

#include "SetProperties.h"

#include "Common/MS/PropVariant.h"
#include "Common/MyFixes.h"
#include "Common/String/StringToInt.h"

#include "Common/Archive/IArchive.h"

namespace Common
{
namespace Props
{

static void ParseNumberString(const CString &s, CComPropVariant &prop)
{
  LPCTSTR endPtr;
  UINT64 result = String::ConvertStringToUInt64(s, &endPtr);
  if (endPtr - (const TCHAR *)s != s.GetLength())
    prop = CComBSTR(s);
  else if (result <= 0xFFFFFFFF)
    prop = (UINT32)result;
  else
    prop = result;
}

HRESULT SetProperties(IUnknown *unknown, const std::vector<CProperty> &properties)
{
  if (properties.empty())
    return S_OK;
  CComPtr<ISetProperties> setProperties;
  unknown->QueryInterface(__uuidof(ISetProperties), (void **)&setProperties);
  if (!setProperties)
    return S_OK;

  CStringVector realNames;
  CComPropVariant *values = new CComPropVariant[properties.size()];
  try
  {
    size_t i;
    for(i = 0; i < properties.size(); i++)
    {
      const CProperty &property = properties[i];
      CComPropVariant propVariant;
      CString name = property.Name;
      if (property.Value.IsEmpty())
      {
        if (!name.IsEmpty())
        {
          wchar_t c = name[name.GetLength() - 1];
          if (c == _T('-'))
            propVariant = false;
          else if (c == _T('+'))
            propVariant = true;
          if (propVariant.vt != VT_EMPTY)
            name = name.Left(name.GetLength() - 1);
        }
      }
      else
        ParseNumberString(property.Value, propVariant);
	  realNames.push_back(name);
      values[i] = propVariant;
    }
    std::vector<const wchar_t *> names;
	names.reserve(realNames.size());
    for(i = 0; i < realNames.size(); i++)
      names.push_back((const wchar_t *)realNames[i]);
    
    HRESULT hRes = setProperties->SetProperties(&names.front(), values, names.size());
	if(S_OK != hRes)
		return hRes;
  }
  catch(...)
  {
    delete []values;
    throw;
  }
  delete []values;
  return S_OK;
}

}
}